#pragma once
#include <atomic>
namespace MySTL {
// 控制块，存放引用技术器
class ControlBlock {
public:
  // 引用计数器
  std::atomic_int ref_count{1};
};
template <typename T> class shared_ptr {
public:
  // 默认构造函数
  shared_ptr<T>() : m_pointer_(nullptr), m_control_block_ptr_(nullptr){};
  explicit shared_ptr<T>(T *ptr) : m_pointer_(ptr) {
    if (m_pointer_) {
      m_control_block_ptr_ = new ControlBlock();
    } else {
      m_control_block_ptr_ = nullptr;
    }
  };

  // 析构函数
  ~shared_ptr<T>() {
    if (m_control_block_ptr_) {
      // 引用计数器--
      if (m_control_block_ptr_ &&
          m_control_block_ptr_->ref_count.fetch_sub(1) == 1) {
        // 资源释放
        delete m_pointer_;
        delete m_control_block_ptr_;
      }
    }
  };
  // 拷贝复制构造函数
  shared_ptr<T>(const shared_ptr<T> &other) {
    if (other.m_control_block_ptr_) {
      other.m_control_block_ptr_->ref_count.fetch_add(1);
    }
    m_control_block_ptr_ = other.m_control_block_ptr_;
    m_pointer_ = other.m_pointer_;
  };
  // 拷贝赋值运算符
  // 1.自赋值判断
  // 2.
  shared_ptr<T> &operator=(const shared_ptr<T> &other) {
    if (this == &other)
      return *this;
    // 1.释放当前资源
    if (m_control_block_ptr_ &&
        m_control_block_ptr_->ref_count.fetch_sub(1) == 1) {
      delete m_control_block_ptr_;
      delete m_pointer_;
      m_pointer_ = nullptr;
      m_control_block_ptr_ = nullptr;
    }
    // 引用计数器++
    if (other.m_control_block_ptr_) {
      other.m_control_block_ptr_->ref_count.fetch_add(1);
    }
    m_pointer_ = other.m_pointer_;
    m_control_block_ptr_ = other.m_control_block_ptr_;
    return *this;
  };
  // 移动构造函数
  shared_ptr<T>(shared_ptr<T> &&other) {
    m_pointer_ = other.m_pointer_;
    other.m_pointer_ = nullptr;
    m_control_block_ptr_ = other.m_control_block_ptr_;
    other.m_control_block_ptr_ = nullptr;
  };
  // 移动赋值运算符
  shared_ptr<T> &operator=(shared_ptr<T> &&other) {
    if (&other == this)
      return *this;
    // 销毁资源
    if (m_control_block_ptr_ &&
        m_control_block_ptr_->ref_count.fetch_sub(1) == 1) {
      delete m_pointer_;
      delete m_control_block_ptr_;
    }
    m_pointer_ = other.m_pointer_;
    other.m_pointer_ = nullptr;
    m_control_block_ptr_ = other.m_control_block_ptr_;
    other.m_control_block_ptr_ = nullptr;
    return *this;
  };
  // 解引用运算符
  T &operator*() const { return *m_pointer_; };
  // 箭头运算符
  T *operator->() const { return m_pointer_; };
  // 重置
  T *get() const { return m_pointer_; };
  // 查看引用计数
  int use_count() {
    if (m_control_block_ptr_) {
      return m_control_block_ptr_->ref_count;
    } else {
      return 1;
    }
  }

  template <typename X> void reset(X *ptr) {
    if (m_control_block_ptr_ &&
        m_control_block_ptr_->ref_count.fetch_sub(1) == 1) {
      // 资源释放
      delete m_control_block_ptr_;
      m_control_block_ptr_ = nullptr;
      delete m_pointer_;
      m_pointer_ = nullptr;
    }
    m_pointer_ = ptr;
    if (m_pointer_) {
      m_control_block_ptr_ = new ControlBlock;
    } else {
      m_control_block_ptr_ = nullptr;
    }
  };

private:
  // 资源原始指针
  T *m_pointer_;
  ControlBlock *m_control_block_ptr_;
};

} // namespace MySTL